package businessLogic;

import java.io.Serializable;
import java.util.ArrayList;

import comunications.Ping;
import comunications.SendDeathNotification;
import comunications.SendTable;
import crashManager.DeathList;

import Graphic.ChoiseValueJoker;
import Graphic.DialogBox;
import Graphic.DialogBoxExit;
import Graphic.DraftLayout;
import Graphic.ThreadedDialogBox;
import Graphic.WaitingForm;

import gameState.Baloon;
import gameState.Player;
import gameState.Ring;
import gameState.Table;
import scala40rules.*;
import sounds.Sound;

public class PlayerActions extends Player implements Cloneable, Serializable{

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	//global informations
	private Table table;

	//utility informations
	private static final int maxCardsOnHands=13;
	private static final int maxCardSetSize=6;
	private static final int basicLevel=0;
	private static final int notSuited=-3;
	private static final int maxScore=101;

	//personal informations
	private boolean alreadyDrawnCard;
	private boolean alreadyDiscardedCard;
	private Baloon baloon;

	private Ring ring;

	private DraftLayout graphic= new DraftLayout();

	public PlayerActions(Player p){
		super(p.getName(),p.getIp(),p.getPort(),p.getId());
		//just for testing.....ho dovuto rimuovere il SINGLETON nel Tavolo....percio' ho creato
		//il costruttore sottostante a questo!!!
		table= Table.getInstance();
		ring= Ring.getInstance();
		alreadyDrawnCard=false;
		alreadyDiscardedCard=false;
		baloon = new Baloon();
		graphic.setPlayerActions(this);
//			try{
//				Ping ping = new Ping(this);
//				ping.start();
//				
//			}catch(Exception e){
//				e.printStackTrace();
//			}
		}

	//*-*-*-*-*-*-*-*-*-*-*-*-*-*- METODO UNICAMENTE PER IL TESTING *-*-*-*-*-*-*-*-*-*-*-*-*

	public PlayerActions(Player p,Table t, Ring r){
		super(p.getName(),p.getIp(),p.getPort(),p.getId());
		//TODO just for testing..... costruttore necessario solo in fase di testing
		table= t;
		ring= r;
		alreadyDrawnCard=false;
		alreadyDiscardedCard=false;
		baloon = new Baloon();
	}
	//*-*-*-*-*-*-*-*-*-*-*-*-*-*- METODO UNICAMENTE PER IL TESTING (sopra) *-*-*-*-*-*-*-*-*-*-*-*-*

	public void startGame(){
		//if ( e' stato premuto il tasto PASSA IL TURNO && canICommit) --> commit;
		if(!this.ring.isSameRing(table.getPlayers())){
			table.updateTableWithAlivePlayers(this.ring);
		}

		//just for testing.....senza sinlgeton e in locale
		if ( (this.getId()==1) && (table.getVersion()==1)){
			System.out.println("******** Giocatore "+this.getName()+" sta per SCARTARE una carta");
			this.discardToWell(8);

			this.commit();
		}
		if ((this.getId()==0) && (table.getVersion()==2)){
			System.out.println("******** Giocatore "+this.getName()+" sta per PESCARE una carta");
			this.drawFromHeel();
			System.out.println("******** Giocatore "+this.getName()+" sta per SCARTARE una carta");
			this.discardToWell(3);

			this.commit();
		}
		if ((this.getId()==1) && (table.getVersion()==3)){
			System.out.println("******** Giocatore "+this.getName()+" sta per PESCARE una carta");
			this.drawFromHeel();
			System.out.println("******** Giocatore "+this.getName()+" sta per SCARTARE una carta");
			this.discardToWell(3);

			this.commit();
		}
	}



	//------------------------------------ METODI DI INIZIO E FINE DELLA PARTITA ---------------------------------//

	public boolean missingPlayers(){
		boolean result = false;
		int tablePlayers = table.getPlayers().size();
		int i=0;
		while(!result && (i<tablePlayers)){
			if(!ring.existPlayerInTheRing(table.getPlayer(i))){
				result = true;
				System.out.println("[PlayerActions || missingPlayer()] return "+result);
				return result;
			}
			i++;
		}
		System.out.println("[PlayerActions || missingPlayer()] return "+result);
		return result;
	}
	

	//TODO -------------------------------DA TESTARE---------------------------------------------//
	//EVENTO: il player non ha + carte in mano
	//calcolo i punteggi di tutti i giocatori, aggiorno il vettore score e ricreo un nuovo tavolo(con versione-1)
	public void matchWin(){
		try{
			Sound s = new Sound();
			s.suonaTada();
			
			String text = "Complimenti!!! \n" +
			"Hai vinto questo match.\n";
			try{
				 Thread matchNotification = new ThreadedDialogBox(text,false);
				 matchNotification.start();
                 
            }
            catch(Exception e2){
                System.out.println("[PlayerActions || matchWin()] lanciata eccezione in ThreadedDialogBox");
                e2.printStackTrace();
            }
			
			//prima aggiorno nuovamente il tavolo in base ai giocatori effettivamente partecipanti
			
			if(this.missingPlayers()){
				System.out.println("[PlayerActions || matchWin()] table.getPlayers().size="+table.getPlayers().size()+"  ring.size()="+ring.size());
				table.updateTableWithAlivePlayers(ring);
			}

//			System.out.println("[PlayerActions || matchWin()] sto per resettare il tavolo");
//			//effettuo il reset del tavolo per una nuova partita
//			System.out.println("[PlayerActions || matchWin()] Ring: ");
//			for(int i=0; i<ring.size(); i++){
//				System.out.println("                                "+i+": "+ring.getPlayer(i).getName());
//			}
			table.resetTableForNewMatch(ring);
			System.out.println("[PlayerActions || matchWin()] ring.getMe()"+ring.getMe().getClass().toString());
			table.setWinner(ring.getMe());

			System.out.println(" -------------- HO VINTOOOOOOOOOOOOOOOOO -------------");
			
			//stampe di supporto
			int myPosition = table.getPlayerPosition(this);
			//table.stampaCartePlayer(myPosition);
			table.stamaScore();
		}catch(Exception e) {
				System.out.print("-[Exception]- matchWin ");
				e.printStackTrace();
		}
	}

	//distribuisce le carte
	public void dealCards(){
		try{
			System.out.println("[PlayerActions || dealCards()] ");
			for(int players=0; players < table.getPlayers().size(); players++){
				CardSet startingCards = new CardSet();
				System.out.println("\n  Carte del giocatore "+ table.getPlayer(players).getName() +": ");
				
				//DAI CARTE TAROCCATO!!!!!!!!!!!!
//				startingCards = this.daiCarteTaroccato();
				
				for(int cards=0; cards<13; cards++){
					startingCards.addCard(table.getRandomCardFromHeel());
				}
				
				startingCards.printCardset();
				CardSetList csl = new CardSetList();
				csl.addCardSet(startingCards);
				table.addPlayerCards(csl);
				System.out.println("[PlayerActions || dealCards()] PlayerCards.size()="+table.getPlayersCards().size());
				

			}
			Card c= table.getRandomCardFromHeel();
			//System.out.println("[PlayerAction || dealCards()] al giocatore "+ring.getMyNextPlayer().getName()+" in posizione "+table.getPlayerPosition(ring.getMyNextPlayer())+" viene data la carta "+c.getSymbol()+" "+c.getSuit()+" in + perche' e' il primo");
			table.addToPlayersCards(table.getPlayerPosition(ring.getMyNextPlayer()), basicLevel, c);
//			System.out.println("[PlayereActions || dealCards()] Stampa di controllo:");
//			for(int players=0; players < table.getPlayers().size(); players++){
//				System.out.println("[PlayereActions || dealCards()]          Player="+table.getPlayer(players).getName());
//				for(int cards=0; cards<13; cards++){
//	//				startingCards.add(table.getRandomCardFromHeel());
//					System.out.println("                                            Carta "+cards+":"+table.getPlayerCardSet(players, basicLevel).getCard(cards).getSymbol()+" "+table.getPlayerCardSet(players, basicLevel).getCard(cards).getSuit());
//				}
//			}
			this.setCardsOnHands();
			this.setMyTurnOnGraphic(false);

		}catch (Exception e) {
			System.out.print("-[Exception]- PlayerActions.dealCards ");
			e.printStackTrace();
		}
	}

//-------------------------------------- METODI BASE DEL GIOCO -----------------------------------------//

	//pesca carta dal mazzo coperto
	public void drawFromHeel(){
		try{
			int playerPosition = table.getPlayerPosition(this);
			//boolean correctRangeSize = (table.getPlayersCards().get(playerPosition).size()<= maxCards || table.getPlayersCards().get(playerPosition).size()>0);

			//se il vettore delle carte coperte e' vuoto rimescolo le carte scoperte
			if( ! table.isHeelEmpty()){
				table.popolateHeelFromWell();
			}

			if(!alreadyDrawnCard /*&& correctRangeSize*/){
				System.out.println("[PlayerActions || drawFromHeel] sto pescando...");
				Card cardDrawn= table.getRandomCardFromHeel();

				table.addToPlayersCards(playerPosition,basicLevel, cardDrawn);
				alreadyDrawnCard=true;


				this.setCardsOnHands();

				//stampa di supporto
				table.stampaCartePlayer(playerPosition);
			}
			else{
				System.out.println("-[Error]- [PlayerActions || drawFromHeel] ho gia' pescato percio' posso pescare ");
			}

		}
		catch (Exception e) {
			System.out.print("-[Exception]- drawFromHeel ");
			e.printStackTrace();
		}
	}

	//EVENTO:
	//scarta carta
	public void discardToWell(int positionCard){
		try{
			int playerPosition = table.getPlayerPosition(this);
			System.out.println("[PlayerAction || discardToWell()] table player position"+ playerPosition);
			//boolean correctRangeSize = (table.getPlayerCardSet(playerPosition, basicLevel).size() > maxCards || table.getPlayerCardSet(playerPosition, basicLevel).size()>0);
			System.out.println("[PlayerActions  || discardToWell()] alreadyDrawnCard"+ alreadyDrawnCard +" alreadyDiscardCard"+alreadyDiscardedCard);
			if(!alreadyDiscardedCard && /* correctRangeSize && */ alreadyDrawnCard){
				Card c= table.removePlayerCard(playerPosition, basicLevel, positionCard);
				System.out.println("[PlayerActions || discardToWell]  player"+this.getName()+" scarto la carta "+c.getSymbol()+" "+c.getSuit());
				table.addToWell(c);
				alreadyDiscardedCard=true;

				this.setCardsOnHands();



				//stampe di supporto
				table.stampaCartePlayer(playerPosition);
				System.out.println("ultima carta mazzo scoperto "+table.getWell().getCard(table.getWell().size()-1).getSymbol());

				if(table.getPlayerCardTotal(playerPosition).size()==0){
					this.matchWin();
					this.commit(false);
				}else{
					this.commit();
				}
				
				//scartando passa il turno
				//this.playerCommit();
				
			}else
			{
				System.out.println("-[Error]- [PlayerActions || discardToWell] non posso scartare ");
				System.out.println("          [PlayerActions || discardToWell] alreadyDrawnCard="+alreadyDrawnCard);
				System.out.println("          [PlayerActions || discardToWell] alreadyDiscardedCard="+alreadyDiscardedCard);
			}

		}
		catch (Exception e) {
			System.out.print("-[Exception]- discardToWell ");
			e.printStackTrace();
		}
	}

	//EVENTO: selezione dal menu di "Draw Card from Well"
	//pesca carta dal mazzo scoperto [ricorda di controllare se il giocatore ha gia' sceso 40]
	public void drawFromWell(){
		try{
			boolean correctRangeSize = ( table.getWell().size()>0);
			int playerPosition = table.getPlayerPosition(this);
			boolean alreadyLaid = table.getHasLaid().get(playerPosition);
			if(alreadyLaid && !alreadyDrawnCard && correctRangeSize){
				System.out.println("[PlayerActions || drawFromWell] sto pescando dal mazzo scoperto...");
				Card cardDrawn = table.removeLastCardFromWell();

				table.addToPlayersCards(playerPosition,basicLevel, cardDrawn);
				alreadyDrawnCard=true;


				this.setCardsOnHands();
				//stampa di supporto
				table.stampaCartePlayer(playerPosition);
			}else
			{
				System.out.println("-[Error]- [PlayerActions || drawFromWell] non posso pescare dal mazzo scoperto ");
			}
		}
		catch (Exception e) {
			System.out.print("-[Exception]- drawFromWell ");
			e.printStackTrace();
		}
	}

//----------------------------------- METODI DI GESTIONE CARTE IN MANO ------------------------------//

	//sposta a sinistra(cardPosition) carte in mano
	//IMPORTANTE PRESUPPOSTO: si possono spostare solo le carte in mano e non quelle nel baloon
	//se diverra' possibile spostare anche le carte nel baloon basta prendere in input anche il livello del baloon
	public void moveToLeft(int cardPosition){
		try{
			System.out.println("[PlayerActions || moveToLeft] provo a spostare a sinistra...");
			int playerPosition = table.getPlayerPosition(this);
			if( ((cardPosition-1)>=0) && (cardPosition<table.getPlayerCardSet(playerPosition, basicLevel).size())){
				System.out.println("[PlayerActions || moveToLeft] sto spostando la carta "+table.getPlayerCardSet(playerPosition, basicLevel).getCard(cardPosition).getSymbol()+" a sinistra");
				Card temp = table.getPlayerCardSet(playerPosition, basicLevel).removeCard(cardPosition);
				table.getPlayerCardSet(playerPosition, basicLevel).addCard(cardPosition-1, temp);
			}else{ System.out.println("spostamento non effettuato, OutOfBound");}

			//stampa di supporto

			table.stampaCartePlayer(playerPosition);
		}catch(Exception e) {
				System.out.print("-[Exception]- moveToLeft ");
				e.printStackTrace();
		}
	}


	//sposta a destra
	//IMPORTANTE PRESUPPOSTO: si possono spostare solo le carte in mano e non quelle nel baloon
	//se diverra' possibile spostare anche le carte nel baloon basta prendere in input anche il livello del baloon
	public void moveToRight(int cardPosition){
		try{
			System.out.println("[PlayerActions || moveToRight] provo a spostare a destra...");
			int playerPosition = table.getPlayerPosition(this);
			if( (cardPosition >=0) && (cardPosition<table.getPlayerCardSet(playerPosition, basicLevel).size()-1) ){
				System.out.println("[PlayerActions || moveToRight] sto spostando la carta "+table.getPlayerCardSet(playerPosition, basicLevel).getCard(cardPosition).getSymbol()+" a destra");
				Card temp = table.getPlayerCardSet(playerPosition, basicLevel).removeCard(cardPosition+1);
				table.getPlayerCardSet(playerPosition, basicLevel).addCard(cardPosition, temp);
			}else{ System.out.println("spostamento non effettuato, OutOfBound");}

			//stampa di supporto

			table.stampaCartePlayer(playerPosition);
		}catch(Exception e) {
				System.out.print("-[Exception]- moveToRight ");
				e.printStackTrace();
		}
	}

	//si controlla che ci siano le condizioni sufficienti per poter mettere una carta a terra:
	// Condizione1 --> il cardSet a tavola non deve essere gia' della grandezza massima (6)
	//          oppure il cardSet a tavola contiene un joker
	// Condizione2 --> il giocatore deve gia' aver aperto il gioco
	public boolean canIPutCardOnTheTable(CardSet cs){
		try{
			int playerPosition = table.getPlayerPosition(this);
			boolean correctSize = (cs.existJoker() || ((cs.size()+1)<=maxCardSetSize) );
			System.out.println("[PlayerActions || canIPutCardOnTheTable()] correctSize="+correctSize+" " +
					"hasLaid="+table.getHasLaid(playerPosition));
			return (  correctSize && (table.getHasLaid(playerPosition)) );
		}
		catch (Exception e) {
			System.out.print("-[Exception]- canPutCardOnTheTable() ");
			e.printStackTrace();
			return false;
		}
	}



	//in realtÔøΩ ci sarÔøΩ un solo metodo che chiama la checkReplaceAndAdd
	//aggiungi carta a cardSet gia' giu'
	//sostituisci matta in cardSet gia' giu'
	public void tryToAddOrRepleaceCard(int cardPosition, int cardSetPosition){
		try{
			int playerPosition = table.getPlayerPosition(this);
			CardSet cardSetOnTheTable= table.getCardSetOnTheTable(cardSetPosition);
			Card card = table.getPlayerCardSet(playerPosition, basicLevel).getCard(cardPosition);

			for(int j=0; j<cardSetOnTheTable.size(); j++){
				System.out.println("[PlayerActions || tryToAddOrRepleace()] cardSetOnTheTable "+ cardSetOnTheTable.getCard(j).getSymbol()+" "+cardSetOnTheTable.getCard(j).getSuit());
			}

			if( this.canIPutCardOnTheTable(cardSetOnTheTable)){

				//si tenta di effettuare il repleace
				CardSet csResult = cardSetOnTheTable.replaceJokerInValidSet(card);
                if( csResult!= null){
    					System.out.println("[PlayerActions || addCardToValidSet()] ha sostituito il joker");
//    					for(int i=0; i<csResult.size(); i++){
//    						System.out.println("                                        -"+i+"- "+csResult.getCard(i).getOrdinalValue()+" "+csResult.getCard(i).getSuit());
//    					}
                    table.setCardSetOnTheTable(cardSetPosition, csResult);
                    table.removePlayerCard(playerPosition, basicLevel, cardPosition);
                    table.addToPlayersCards(playerPosition, basicLevel, new Card(14, "Joker", " ",true, "src/cards/joker.png","src/small_cards/joker.png"));
                }
				else if(!((table.getPlayerCardTotal(playerPosition).size()==1) && alreadyDrawnCard)){
                    System.out.println("-Errore- [PlayerActions || tryToAddOrRepleaceCard()] non ha sostituito nulla, tento di aggiungere la carta");
                    csResult = cardSetOnTheTable.addCardToValidSet(card);
                    if( csResult!= null){
                    	System.out.println("[PlayerActions || addCardToValidSet()] ha aggiunto la carta, il nuovo cardSet e' il seguente");
		                      for(int i=0; i<csResult.size(); i++){
								System.out.println("                                        -"+i+"ÔøΩ "+csResult.getCard(i).getOrdinalValue()+" "+csResult.getCard(i).getSuit());
		                      }
                    	table.setCardSetOnTheTable(cardSetPosition, csResult);
                    	table.removePlayerCard(playerPosition, basicLevel, cardPosition);
                    }
                    else{
                        System.out.println("-Errore- [PlayerActions || tryToAddOrRepleaceCard()] non ha aggiunto nulla");
                    }
				}else{
					System.out.println("-Errore- [PlayerActions || tryToAddOrRepleaceCard()] non posso attaccare perche' rimarrei senza carte da scartare");
				}
			}else{
				System.out.println("-Errore- [PlayerActions || tryToAddOrRepleaceCard()] canIPutCardOnTheTable = FALSE");
			}

			this.setCardsOnHands();

			//stampa di supporto
			table.stampaCartePlayer(playerPosition);
			table.stampaCarteSulTavolo();
		}
		catch (Exception e) {
			System.out.print("-[Exception]- PlayerActions || tryToAddOrRepleaceCard() ");
			e.printStackTrace();
			System.out.println(e.getMessage());
		}

	}


//------------------------------------------ METODI GESTIONE BALOON ----------------------------------------//


	//EVENTO: pressione del bottone "Remove Line"
	//rimuove un intero cardSet dal baloon, curandosi di toglierlo anche dal tavolo
	//IPOTESI: con la cattura dell'evento, mi viene data il baloonLevel (e percio' la line) da cancellare
	public void removeLevelFromBaloon(int baloonLevel){
		try{
			int playerPosition = table.getPlayerPosition(this);

			if( (baloonLevel>=0) && (baloonLevel<this.baloon.size()) ){

				System.out.println("[PlayerActions || removeLevelFromBaloon] sto rimuovendo il livello "+ baloonLevel +" del baloon...");
				this.baloon.resetJokerAtLevel(baloonLevel);
				
				CardSet cardSetRemovedFromBaloon = this.baloon.removeCardSet(baloonLevel);
				cardSetRemovedFromBaloon.printCardset("[PlayerActions || removeLevelFromBaloon()] Rimosso dal baloon il cardSet:");
				
				int playerCardsLevel = this.translateBaloonLevelToPlayersCardsLevel(baloonLevel);
				System.out.println("[PlayerActions || removeLevelFromBaloon] livello del playersCards " + playerCardsLevel);
				
				CardSet cardSetRemovedFromTable = table.removePlayerCard(playerPosition, playerCardsLevel);
				cardSetRemovedFromTable.printCardset("[PlayerActions || removeLevelFromBaloon()] Rimosso di conseguenza dal tavolo il cardSet:");
				
				table.addToPlayersCards(playerPosition, basicLevel, cardSetRemovedFromBaloon);
				System.out.println("[PlayerActions || removeLevelFromBaloon] sincronizzazione col tavolo effettuata");
				
				this.setCardsOnHands();

			}else{
				System.out.println("-[Error]- [PlayerActions || removeLevelFromBaloon()] impossibile eliminare la riga "+baloonLevel+"; riga inesistente");
			}

			//stampa di supporto
			table.stampaCartePlayer(playerPosition);
			baloon.stampaAllBaloon();
		}
		catch (Exception e) {
			System.out.print("-[Exception]- removeLevelFromBaloon() ");
			e.printStackTrace();
		}
	}

	//EVENTO: pressione del bottone "Reset Baloon"
	//il baloon viene svuotato e tutte le carte che contiene vengono messe in mano(basicLevel) al giocatore
	public void removeAllCardSetFromBaloon(){
		try{
			int playerPosition = table.getPlayerPosition(this);
			System.out.println("[PlayerActions || removeAllCardSetFromBaloon()] svuotamento completo del baloon");

			int i=0;
			while (i<this.baloon.size()){
				this.baloon.resetJokerAtLevel(i);
				CardSet cs = this.baloon.removeCardSet(i);
				CardSet cardSet= this.table.getPlayerCardSetList(playerPosition).removeCardSetFromList(this.translateBaloonLevelToPlayersCardsLevel(i));
				this.table.addToPlayersCards(playerPosition, basicLevel, cs);

			}
//			int baloonLevel=0;
//			for(int i=0; i<baloon.size(); i++){
//				this.removeLevelFromBaloon(baloonLevel);
//			}
			
			//this.table.stampaCartePlayer(playerPosition);
			this.setCardsOnHands();

			table.stampaCartePlayer(table.getPlayerPosition(this));
			baloon.stampaAllBaloon();
		}
		catch (Exception e) {
			System.out.print("-[Exception]- removeAllCardSetFromBaloon() ");
			e.printStackTrace();
		}
	}


	//EVENTO: click sulla carta
	//IPOTESI: la cattura dell'evento chiama questo metodo passandogli la posizione della carta
	public boolean addCardToBaloon(int cardPosition){
		try{
			int playerPosition = table.getPlayerPosition(this);
			System.out.println("[PlayerActions || addCardToBaloon] sto mettendo la carta in posizione"+cardPosition+" nel baloon");
			System.out.println("[PlayerActions || addCardToBaloon] Carta: "
					+ table.getPlayerCardSet(playerPosition, basicLevel).getCard(cardPosition).getSymbol()
					+" "+table.getPlayerCardSet(playerPosition, basicLevel).getCard(cardPosition).getSuit()
					+" nel baloon...");
			//inserimento della carta nell'ultimo livello gestibile del baloon,
			//solo se l'operazione ha avuto effettivamente successo --> rimozione della carta dalle
			//mani del giocatore (basicLevel) ed inserimento nei livelli successivi (corrispondenti al baloon)

			//Card card=table.removePlayerCard(playerPosition, basicLevel, cardPosition);
			Card card=table.getPlayerCardSet(playerPosition, basicLevel).getCard(cardPosition);
			boolean result = this.baloon.addCardToLastBaloonLevel(card);
			if(result){
				table.removePlayerCard(playerPosition, basicLevel, cardPosition);
				int level= baloon.size();
				table.addToPlayersCards(playerPosition, level, card);
			}

			this.setCardsOnHands();
			//stampa di supporto
			table.stampaCartePlayer(playerPosition);
			this.baloon.stampaAllBaloon();
            return result;
		}
		catch (Exception e) {
			System.out.print("-[Exception]- addCardToBaloon ");
			e.printStackTrace();
                        return false;
		}
	}

	//EVENTO: click sul bottone "new Line"
	public boolean addLineToBaloon(){
		try{
			int playerPosition = table.getPlayerPosition(this);
			System.out.println("[PlayerActions || addLineToBaloon] sto aggiungendo una riga al baloon," +
					" percio' controllo che la riga precedente sia un CardSet valido");

			boolean result = this.baloon.newBaloonLevel();
			if(!result)
				System.out.println("-[Error]- [PlayerActions || addLineToBaloon] impossibile aggiungere nuova riga");
			else{
				if (this.baloon.getBaloonLevel(this.baloon.size()-2).mustChooseJokerValue()){
					ChoiseValueJoker joker=new ChoiseValueJoker(this);
				 	joker.message(this.baloon.getBaloonLevel(this.baloon.size()-2).getPossibleJokerValue());
				}
//				CardSet lastValidCardSet = new CardSet();
//				lastValidCardSet.add(this.baloon.getBaloonLevel(this.baloon.size()-2));
//				System.out.println("[PlayerActions || addLineToBaloon()] ---------------"+lastValidCardSet.getCard(0).getSymbol());
//				int maxLoop = lastValidCardSet.size();
//				while(lastValidCardSet.mustChooseJokerValue() && maxLoop>0){
//
//														System.out.println("[PlayerActions || addLineToBaloon()] --------- DEVO FAR SCEGLIERE");
//                                                        for(int i=0; i<lastValidCardSet.getPossibleJokerValue().size(); i++)
//                                                        {
//                                                            System.out.println(" ====== Joker: " + lastValidCardSet.getPossibleJokerValue().getCard(i).getSuit());
//                                                        }
//					 ChoiseValueJoker joker=new ChoiseValueJoker();
//					 joker.message(lastValidCardSet.getPossibleJokerValue());
//
//					 Thread.sleep(500);
//					 int scelta = joker.getSuitedJoker();
//					 System.out.println(" SCELTA FATTA "+ scelta);
//
//					 lastValidCardSet.setCard(lastValidCardSet.getFirstJokerPosition(), lastValidCardSet.getPossibleJokerValue().getCard(scelta));
//					 //TODO chiamare metodo in graphics!!!
//					 lastValidCardSet.removeCard(0);
//					 lastValidCardSet.add(this.baloon.getBaloonLevel(this.baloon.size()-2));
//					 for(int i=0; i<lastValidCardSet.getPossibleJokerValue().size(); i++)
//                     {
//                         System.out.println(" ====== Joker: " + lastValidCardSet.getPossibleJokerValue().getCard(i).getSuit());
//                     }
//					 maxLoop--;
//				}
			}


			//stampa di supporto
			table.stampaCartePlayer(playerPosition);
			return result;
		}
		catch (Exception e) {
			System.out.print("-[Exception]- addLineToBaloon ");
			e.printStackTrace();
			System.out.print("\n");
			return false;
		}
	}


	public int translatePlayersCardsLevelToBaloonLevel(int playersCardsLevel){
		return playersCardsLevel-1;
	}

	public int translateBaloonLevelToPlayersCardsLevel(int baloonLevel){
		return baloonLevel+1;
	}

	//controlla se ho gia' scalato 40
	public boolean haveIalreadyOpenTheGame(){
		int playerPosition = table.getPlayerPosition(this);
		System.out.println("[PlayerActions || haveIalreadyOpenTheGame()] "+(table.getHasLaid(playerPosition)));
		return (table.getHasLaid(playerPosition));
	}
	
	public boolean remainAnyCardsToDiscard(){
		int playerPosition = table.getPlayerPosition(this);
		int sizeCardsOnHands = table.getPlayerCardSet(playerPosition, basicLevel).size();
		boolean isValidLastBaloonLevel;
		if(this.baloon.getBaloonLevel(this.baloon.size()-1).size()>0){
			isValidLastBaloonLevel = this.baloon.getBaloonLevel(this.baloon.size()-1).isValidSet();
		}else{
			isValidLastBaloonLevel=false;
		}
		System.out.println("[PlayerActions || remainAnyCardsToDiscard()] sizeCardsOnHands="+sizeCardsOnHands+" isValidLastBaloonLevel="+isValidLastBaloonLevel);
		return !(isValidLastBaloonLevel && (sizeCardsOnHands == 0));
	}

	//EVENTO: click sul pulsante "Scala"
	//vengono messi sul tavolo tutti e SOLO i cardSet validati!!!
	//l'unico che potrebbe non essere valido e' l'ultimo e, in quel caso, rimane nel baloon
	public String putDownBaloon(){
		try{
			if(!(this.baloon.getBaloonLevel(this.baloon.size()-1).mustChooseJokerValue())){
				if(this.haveIalreadyOpenTheGame()){
					if(remainAnyCardsToDiscard() || !alreadyDrawnCard){
						this.layAllValidCardSetInTheBaloon();
						graphic.resetBaloon();
						this.updateGraphicBaloon();
						return "";
					}
					return "Attenzione: non avresti carte da scartare";
				}
				else{
					if(baloon.canOpen()){
						if(remainAnyCardsToDiscard() || !alreadyDrawnCard){
							this.openTheGame();
							graphic.resetBaloon();
							this.updateGraphicBaloon();
							return "";
						}
						return "Attenzione: non avresti carte da scartare";
					}
					else{
							System.out.println("-[Error]- [PlayerActions || nonMiVieneUnNomePerDireScalaCardSetDelBaloon] " +
												"non posso scalare perche' non ho 40");
							return "Attenzione: non hai raggiunto il punteggio di 40.";
						}
					}
			}else{
				return "Attenzione: devi prima validare l'ultima riga";
			}
			
		}
		catch (Exception e) {
			System.out.print("-[Exception]- nonMiVieneUnNomePerDireScalaCardSetDelBaloon ");
			e.printStackTrace();
			return "-Exception-";
		}
	}

	public void layAllValidCardSetInTheBaloon(){
		try{
			int playerPosition = table.getPlayerPosition(this);

			//rimuovo i cardSet validi dal Baloon
		
			
			CardSetList csl = this.baloon.removeAllValidCardSet();
			

			//li aggiungo a tavola
			table.addCardSetListOnTheTable(csl);


			//se non tutti i cardSet presenti nel baloon erano validi
			//  rimuovo dal baloon e percio' dal vettore PlayersCards tutti i livelli
			//  corrispondenti al baloon ECCETTO l'ultimo che non e' stato validato
			int size = this.table.getPlayerCardSetList(playerPosition).size();
			if( this.baloon.size()== 1)
				size = this.table.getPlayerCardSetList(playerPosition).size()-1;
			

			//rimuovo i cardSet validi(gia' messi sul tavolo) anche da playersCards nei livelli del baloon
			for(int i=1; i<size; i++){
					table.removePlayerCard(playerPosition, 1);
			}

			//stampa di supporto
			table.stampaCartePlayer(playerPosition);
			table.stampaCarteSulTavolo();
		}
		catch (Exception e) {
			System.out.print("-[Exception]- layAllValidCardSetInTheBaloon ");
			e.printStackTrace();
		}
	}

	public boolean openTheGame(){
		try{
			int playerPosition = table.getPlayerPosition(this);
            System.out.println("[PlayerActions || openTheGame] apro il gioco, infatti hasLaid ÔøΩ "+(table.getHasLaid(playerPosition)));

			if(baloon.canOpen()){
				//aggiungo le carte del baloon sul tavolo

				CardSetList csl = this.baloon.getAllValidBaloonLevel();
				table.addCardSetListOnTheTable(csl);
				//rimuovo i cardSet validi dal baloon

				this.baloon.removeAllValidCardSet();

				System.out.println("[PlayerActions || openTheGame()] -------- SIZE BALOON "+this.baloon.size());

				//se non tutti i cardSet presenti nel baloon erano validi
				//  rimuovo dal baloon( e percio' dal vettore PlayersCards) tutti i livelli
				//  corrispondenti al baloon ECCETTO l'ultimo che sicuramente e' l'unico che non stato validato
				int size = this.table.getPlayerCardSetList(playerPosition).size();
				if( this.baloon.size()== 1)
					size = this.table.getPlayerCardSetList(playerPosition).size()-1;
				else{
					//TODO gestireeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee
					if (csl.getCardSet(csl.size()-1).mustChooseJokerValue()){
						ChoiseValueJoker joker=new ChoiseValueJoker(this);
					 	joker.message(csl.getCardSet(csl.size()-1).getPossibleJokerValue());
					}
				}
				
				//rimuovo i cardSet validi anche da playersCards in corrispondenza coi livelli del baloon
				int i=1;
				while(i < size){
						table.removePlayerCard(playerPosition, 1);
						i++;
				}

				table.setHasLaid(playerPosition, true);

				//stampa di supporto
				table.stampaCartePlayer(playerPosition);
				table.stampaCarteSulTavolo();

				return true;

			}else{
				System.out.println("-[Error]- [PlayerActions || openTheGame] non posso aprire il gioco scalando 40 ");
				return false;
			}
		}
		catch (Exception e) {
			System.out.print("-[Exception]- openTheGame ");
			e.printStackTrace();
			return false;
		}
	}



//---------------------------------------- METODI DI SUPPORTO PER LA COMUNICAZIONE --------------------------//

	public Table getTable(){
		return table;
	}

	public void setTableNextCurrentPlayer(){
		if(table.getVersion()==0){
			//il nextPlayer sara' il mazziere
			System.out.println("[PlayerActions || setTableNextCurrentPlayer] il prox currentPlayer sara' il mazziere");
			table.setCurrentPlayer(table.getFirstDealer());
		}else{
			//il nextPlayer sara' il giocatore accanto a me
			table.setCurrentPlayer(ring.getMyNextPlayer());
		}
		System.out.println("[PlayerActions || setTableNextCurrentPlayer] il prossimo giocatore sara' "+ table.getCurrentPlayer().getName());
	}

	public boolean amInextCurrentAlivePlayer(){
		boolean result;
		System.out.println("[PlayerAction || amInextCurrentPlayerAlive()] cerco il successore del CurrentPlayer "+table.getCurrentPlayer().getName()+" morto.");
		Player successiveTablePlayer = table.getSuccessivePlayer(table.getCurrentPlayer());
		System.out.println("[PlayerAction || amInextCurrentPlayerAlive()] successivePlayer sarebbe "+successiveTablePlayer.getName());
		if(!ring.existPlayerInTheRing(successiveTablePlayer)){
            System.out.println("[PlayerAction || amInextCurrentPlayerAlive()] ");
			int playersSize = table.getPlayers().size();
			int i=0;
			boolean found = false;
			while(i<playersSize && !found){
				if(!ring.existPlayerInTheRing(successiveTablePlayer)){
					System.out.println("[PlayerAction || amInextCurrentPlayerAlive()] "+successiveTablePlayer.getName()+" e' gia' stato eliminato");
					successiveTablePlayer = table.getSuccessivePlayer(successiveTablePlayer);
					System.out.println("[PlayerAction || amInextCurrentPlayerAlive()] successivePlayer sarebbe "+successiveTablePlayer.getName());
				}else{
					found = true;
				}
				i++;
			}
		}
		result = successiveTablePlayer.equalPlayer(ring.getMe());
		System.out.println("[PlayerAction || amInextCurrentPlayerAlive()] "+ result );
		return result;
	}

	public boolean isDeadCurrentPlayer(){
		System.out.println("[PlayerAction || isDeadCurrentPlayer()] "+ !( ring.existPlayerInTheRing(table.getCurrentPlayer()) ));
		return !(ring.existPlayerInTheRing(table.getCurrentPlayer()));
	}

	public boolean isMyTurn(){
		boolean result = ( table.getCurrentPlayer().equalPlayer(ring.getMe()));
		System.out.println("[PlayerActions || isMyTurn()] -------------------------------"+ result);
        return result;
	}


	public boolean isMyTurnToDeal(){
		System.out.println("[PlayerAction || isMyTurnToDeal()] "+( (table.getVersion() == 0) &&  this.isMyTurn() ));
		int playerPosition= table.getPlayerPosition(this);
		return ( (table.getVersion() == 0) &&  this.isMyTurn() && (table.getPlayerCardSet(playerPosition, basicLevel).size()==0));
	}


	public boolean someoneWon(){
		System.out.println("[PlayerAction || someoneWon()] "+( (table.getVersion() == -1) && (table.getWinner()!= null) ));
		return ( (table.getVersion() == -1) && (table.getWinner()!= null) );
	}


	public boolean isTheFirstTurn(){
		System.out.println("[PlayerAction || isTheFirstTurn()] "+( (table.getPlayerCardTotal(table.getPlayerPosition(this)).size()==(this.maxCardsOnHands+1)) && (this.isMyTurn()) ));
		return ( (table.getPlayerCardTotal(table.getPlayerPosition(this)).size()==(this.maxCardsOnHands+1)) && (this.isMyTurn()) );
	}

	public boolean isTheFirstMatch(Table t){
		System.out.println("[PlayerAction || isTheFirstMatch()] "+( (t.getVersion()==-1) && (t.getWinner()==null) ));
		return ( (t.getVersion()==-1) && (t.getWinner()==null) );
	}

	public void manageTable(Table t){
		System.out.println("\n ------------------Nuova Versione "+t.getVersion()+" ----------------------");
		if( this.isTheFirstMatch(t)){
			table = t;
			table.incrementVersion();
		}else{
			System.out.println("------------------ tavolo vecchio ----------------------------------");
			table.stampaTuttoTavolo();
			int ringPlayerPosition = ring.getPlayerPosition(this);
			int tablePlayerPosition = table.getPlayerPosition(this);
				System.out.println("[PlayerActions || manageTable()] player position ring "+ ringPlayerPosition);
				System.out.println("                                 player position table "+ tablePlayerPosition);
			table.tableSincronize(t, ringPlayerPosition, tablePlayerPosition, this.missingPlayers());
			System.out.println("------------------ tavolo sincronizzato ----------------------------");
			table.stampaTuttoTavolo();
			
			//update intefraccia grafica
			this.setCardsOnHands();
			this.graphic.draw();
			this.setGraphicScore();
			this.graphic.updateDiscard(this.getLastCardFromWell());
			System.out.println("[PlayerActions || manageTable()]    graphic sincronizzato ");
			

			//controllo se sono morti dei giocatori tra il precedente turno e l'attuale
			//aggiorno il tavolo solo se sono il giocatore di turno
			if( this.missingPlayers() && this.isMyTurn()){
				table.updateTableWithAlivePlayers(ring);
				table.incrementVersion();
				this.setGraphicScore();
				System.out.println("\n[PlayerActions || manageTable()] tavolo aggiornato in base ai giocatori effettivamente partecipanti ");
			}
		}

		if( this.someoneWon()){
			System.out.println("-------------------- "+table.getWinner().getName()+" WINNER -----------------");
			//TODO mostro sulla grafica che c'e' qualcuno che ha vinto
			if(table.getScore(table.getPlayerPosition(this))>maxScore){
				System.out.println("[PlayerActions || manageTable()] Ho realizzato un punteggio maggiore di 101 percio' ho perso");
				
				Sound s = new Sound();
				s.suonaLoser();
				
				DeathList dl = DeathList.getInstance();
	            dl.addDeathPlayer(ring.getMe());
	            try{
	                 Thread sdn = new SendDeathNotification();
	                 sdn.sleep(200);
	                 sdn.start();
	                 
	                 String text = "Game Over. \n" +
						"Hai raggiunto il punteggio di "+table.getScore(table.getPlayerPosition(this))+
 						" e il massimo e' 101.";
	                 try{
						 Thread matchNotification = new ThreadedDialogBox(text,true);
						 matchNotification.start();
		                 
		            }
		            catch(Exception e2){
		                System.out.println("[PlayerActions || manageTable()] lanciata eccezione in ThreadedDialogBox");
		                e2.printStackTrace();
		            }
	            }
	            catch(Exception e2){
	                System.out.println("[PlayerActions || manageTable()] lanciata eccezione in SendDeathNotification");
	                e2.printStackTrace();
	                String text = "Game Over. \n" +
					"Hai raggiunto il punteggio di "+table.getScore(table.getPlayerPosition(this))+
						" e il massimo e' 101.";
                 try{
					 Thread matchNotification = new ThreadedDialogBox(text,true);
					 matchNotification.start();
	                 
	            }
	            catch(Exception e3){
	                System.out.println("[PlayerActions || manageTable()] lanciata eccezione in ThreadedDialogBox");
	                e3.printStackTrace();
	            }
	            }
			}else{
				String text = "Hai Perso. \n" +
				"Il vincitore di questo match e' "+table.getWinner().getName()+" \n" +
				"Inizia ora un nuovo match.";
				try{
					 Thread matchNotification = new ThreadedDialogBox(text,false);
					 matchNotification.start();
	                 
	            }
	            catch(Exception e2){
	                System.out.println("[PlayerActions || manageTable()] lanciata eccezione in ThreadedDialogBox");
	                e2.printStackTrace();
	            }
				this.baloon = new Baloon();
                                graphic.resetBaloon();
				this.updateGraphicBaloon();
			}
		}else{
			if( this.isMyTurnToDeal()){
				this.dealCards();

				//forse questa operazione va' fatta dopo che il msg di update fa un giro completo
				//percio' ho commentato
//				table.setCurrentPlayer(ring.getMyNextPlayer());
//				System.out.println("ring.getMyNextPlayer"+ring.getMyNextPlayer().getName());

				table.incrementVersion();
				//this.commit();
			}else{
					if( this.isTheFirstTurn()){
						System.out.println("[PlayerActions || manageTable()] Sono il primissimo giocatore e ho 14 carte ");
						this.alreadyDrawnCard = true;
						//this.startGame();

						setMyTurnOnGraphic(true);
					}else{
						if( this.isMyTurn() ){
							System.out.println("[PlayerActions || manageTable()] ------------------------------- gioco!!!");
							//this.startGame();
							setMyTurnOnGraphic(true);
						}
					}
				}
		}
	}



	//gestisce 4 casi:
	//1- ho vinto e tutti lo sanno (versione=-1 && Winner=this) --->aggiorno il tavolo e passo il turno al mazziere
	//2- l'ultima versione del tavolo ha fatto il giro dei giocatori (currentPlayer=this)-->passo il turno
	//3- mi arriva un tavolo in cui il CurrentPlayer non e' + in gioco e io sono il suo successore ---> mi autosetto CurrentPlayer
	//4- ignoro il tavolo che mi e' stato spedito perche' non contiene modifiche significative
	//    il boolean che da in output indica se rispedire il tavolo nel ring (sendTable) oppure no
	public boolean sameVersionManager(){
		//System.out.println("[PlayerAction || sameVersionManger()] versione n"+table.getVersion()+" currentPlayer="+table.getCurrentPlayer().getName());

		//gestione caso 1
		if(this.someoneWon() && this.isMyTurn()){
			//aggiorno nuovamente il tavolo in base ai giocatori effettivamente partecipanti
			//per maggiore sicurezza
			System.out.println("[PlayerActions || sameVersionManager()] qualcuno ha vinto ed isMyTurn() = true");
			if(this.missingPlayers()){
//			if(table.getPlayers().size()!= ring.size()){
				System.out.println("[PlayerActions || sameVersionManager()] updateTableWithAlivePlayers");
				table.updateTableWithAlivePlayers(ring);
			}
				table.setWinner(null);
				this.table.incrementVersion();
				this.setTableNextCurrentPlayer();
				this.setGraphicScore();
				//TODO controllare che non invio due volte il tavolo 
				//this.commit(false);
			
			return true;
		}

		//gestione caso 2
		if(this.isMyTurn() && !graphic.isMyTurn()/*&& this.canICommit()*/){

			this.setTableNextCurrentPlayer();
			this.setGraphicScore();
			//Non credo sia giusto fare commit perche' cosi' verrebbe aggiornata la versione del tavolo!!
			table.incrementVersion();

			return true;
		}

		//gestione caso 3
		if (this.isDeadCurrentPlayer() && this.amInextCurrentAlivePlayer()){

			System.out.println("[PlayerActions || sameVersionManager()] Mi autoeleggo a CurrentPlayer" +
								"ed incremento la versione del tavolo");
			table.setCurrentPlayer(ring.getMe());

			if( this.missingPlayers() && this.isMyTurn()){
				table.updateTableWithAlivePlayers(ring);
				this.setGraphicScore();
				System.out.println("\n[PlayerActions || sameVersionManager()] tavolo aggiornato in base ai giocatori effettivamente partecipanti ");
			}
			
			// e' necessario incrementare la versione perche' altrimenti gli altri giocatori
			//non sincronizzerebbero il tavolo con me come nuovo currentPlayer
			table.incrementVersion();
			this.setMyTurnOnGraphic(true);

			return true;
		}

		//gestione caso 4
		return false;
	}

	//TODO
	public boolean canICommit(){

		if( table.getVersion()==1){
			return this.alreadyDiscardedCard;
		}else{
			return (this.alreadyDiscardedCard && this.alreadyDrawnCard);
		}
	}

	//EVENTO: pressione del tasto "Passa il turno"
	public String playerCommit(){
		try{
			if ( !alreadyDrawnCard ){
				return "Error: you must draw and discard a card before";
			}else{
				if( !alreadyDiscardedCard){
					return "Error: you must discard a card before";
				}else{
					//TODO COMMIT
					//TODO GRAPHIC.SETBUTTONRED
					//setMyTurnOnGraphic(true);
					this.commit();
					return "------ TURNO PASSATO --------";


				}
			}
		}catch (Exception e) {
			System.out.print("-[Exception]- playerCommit ");
			e.printStackTrace();
			return "-Error- player";
		}
	}

	public void commit(){
		this.commit(true);
	}

	public void commit(boolean increment){
		System.out.println("\n -------- COMMIT ---------");
		if(increment)
			table.incrementVersion();
		this.setMyTurnOnGraphic(false);
		this.alreadyDiscardedCard=false;
		this.alreadyDrawnCard=false;
			System.out.println("[PlayerActions || commit()] tento di inviare il tavolo vers. "+table.getVersion()+" al player"+ring.getMyNextPlayer().getName());
	    	Thread st = new SendTable(table, ring.getMyNextPlayer());
	    	st.start();
	}


	//---------------------------------------- METODI DI SUPPORTO PER LA GRAFICA --------------------------//


	public void setCardsOnHands(){
		try{
			int playerPosition = table.getPlayerPosition(this);
			CardSet cs = table.getPlayerCardSet(playerPosition, basicLevel);
			graphic.setCards(cs);
			graphic.setVisibleCards();
		}
		catch (Exception e) {
			System.out.print("-[Exception]- setCardsOnHands ");
			e.printStackTrace();
		}
	}

	public Card getCard(int cardPosition){
		try{
			int playerPosition = table.getPlayerPosition(this);
			Card card = table.getPlayerCardSet(playerPosition, basicLevel).getCard(cardPosition);
			return card;
		}
		catch (Exception e) {
			System.out.print("-[Exception]- getCard ");
			e.printStackTrace();
			return new Card();
		}
	}

	public DraftLayout getGraphic() {
		return graphic;
	}

	public Baloon getBaloon(){
		return baloon;
	}

	public int getLastBaloonLineNumber(){
		return this.baloon.getLastLevel();
	}

	public CardSet getLastBaloonLine(){
		if(this.baloon.size()==0){
			return new CardSet();
		}else{
			return this.baloon.getBaloonLevel(this.baloon.size()-1);
		}
	}

    public CardSetList getCardsOnTheTable(){
        try{
			CardSetList csl = table.getCardSetOnTheTable();
			return csl;
		}
		catch (Exception e) {
			System.out.print("-[Exception]- getCardsOnTheTable ");
			e.printStackTrace();
                        return new CardSetList();
		}
    }

    public Card getLastCardFromWell(){
    	try{
    		System.out.println("[PlayerActions || getLastCardFromWell()] ");
    		if(this.table.getHeel().size()==0){
    			return new Card();
    		}else{
    			Card card = table.getLastCardFromWell();
    			return card;
    		}
		}
		catch (Exception e) {
			System.out.print("-[Exception]- getLastCardFromWell ");
			e.printStackTrace();
            return new Card();
		}
    }


	public void runGraphic(){
		System.out.println("--------------------------- RUN GRAPHIC() -------------------------------------------");
		//this.graphic.goGraphic();
		WaitingForm waiting = WaitingForm.getInstance();
		waiting.switchOff();
		
		java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                graphic.setVisible(true);
            }
        });
	}

	public void updateDiscardCard(){
		this.graphic.updateDiscard(this.getLastCardFromWell());
	}

	public void setGraphic(DraftLayout graphic) {
		this.graphic = graphic;
	}

	public void updateCardSetWithJokerSuit(Card jokerCard, int baloonLevel){
		int playerPosition = table.getPlayerPosition(this);
		int tableLevel = this.translateBaloonLevelToPlayersCardsLevel(baloonLevel);

		CardSet cs = this.baloon.getBaloonLevel(baloonLevel);
		int jokerPosition = this.baloon.getBaloonLevel(baloonLevel).getFirstJokerWithoutSuitPosition();
		cs.setCard(jokerPosition, jokerCard);
		this.baloon.setBaloonLevel(baloonLevel, cs);
		this.graphic.refreshLineBaloon(baloonLevel, this.baloon.getBaloonLevel(baloonLevel));

		this.table.removePlayerCard(playerPosition, tableLevel, jokerPosition);
        this.table.addToPlayersCards(playerPosition, tableLevel, jokerCard);


        this.table.stampaCarteSulTavolo();

	}
	
	public void updateGraphicBaloon(){
		int baloonLevel=0;
		try{
			for(baloonLevel=0; baloonLevel<6; baloonLevel++){
				this.graphic.refreshLineBaloon(baloonLevel, this.baloon.getBaloonLevel(baloonLevel));
			}
		}catch(Exception e){
			System.out.println("[PlayerActions || updateGraphicBaloon()] baloon refresh non avvenuto al livello "+baloonLevel);
		}
	}

        public void drawCardsOnTheTable(){
            graphic.draw();

        }

	public void setJokerChosen(int jokerChosen){
		int baloonLevel = this.baloon.size()-2;
		Card card = this.baloon.getBaloonLevel(baloonLevel).getPossibleJokerValue().getCard(jokerChosen);
		this.updateCardSetWithJokerSuit(card, baloonLevel);

//		this.baloon.getBaloonLevel(baloonLevel).setCard(this.baloon.getBaloonLevel(baloonLevel).getFirstJokerWithoutSuitPosition(), card);
//		this.baloon.stampaAllBaloon();
//		this.graphic.refreshLineBaloon(baloonLevel, this.baloon.getBaloonLevel(baloonLevel));

		if (this.baloon.getBaloonLevel(baloonLevel).mustChooseJokerValue()){
			ChoiseValueJoker joker=new ChoiseValueJoker(this);
		 	joker.message(this.baloon.getBaloonLevel(baloonLevel).getPossibleJokerValue());
		}
	}
	
	//per testing
	public void setMyTurnOnGraphic(boolean myTurn){
		this.graphic.setMyTurn(myTurn);
		this.graphic.setLabelTurn(myTurn);
		if(myTurn){
			Sound s = new Sound();
			s.suonaBop();
		}
	}
	
	public void setGraphicScore(){
		String totalScore=" ";
		for (int i=0; i<table.getScore().size(); i++){
			if(table.getPlayer(i).equalPlayer(table.getCurrentPlayer())){
				totalScore = totalScore +" ** "+ table.getPlayer(i).getName() +":  "+table.getScore(i)+" **   ---  ";
			}else{
				totalScore = totalScore + table.getPlayer(i).getName() +":  "+table.getScore(i)+"   ---  ";
			}
		}
		graphic.updateStatus(totalScore);
		
	}
	
	public void startPing(){
		try{
			Ping ping = new Ping(this);
			ping.start();
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public void iAmLegend(){
		System.out.println("*******************************************************");
		System.out.println("*******************************************************");
		System.out.println("**                                                   **");
		System.out.println("**                  I am Legend                      **");
		System.out.println("**                                                   **");
		System.out.println("*******************************************************");
		System.out.println("*******************************************************");
		
		String text = "****** I am Legend ******";
		try{
			 Thread matchNotification = new ThreadedDialogBox(text,true);
			 matchNotification.start();
            
       }
       catch(Exception e2){
           System.out.println("[PlayerActions || manageTable()] lanciata eccezione in ThreadedDialogBox");
           e2.printStackTrace();
       }
		
	}
	 
	
	// ----------------------------------------------- testing --------------------------------
	
	public CardSet daiCarteTaroccato(){
		CardSet startingCards = new CardSet();
		
		Card joker = new Card(14, "Joker", " ",true, "src/cards/joker.png","src/small_cards/joker.png");

		Card assoDiFiori = new Card(1,"A", "diamonds",true, "src/cards/asso_quadri.png","src/small_cards/asso_quadri.png");
		
		Card dueDiFiori = new Card(2,"2", "clubs",true, "src/cards/due_fiori.png","src/small_cards/due_fiori.png");
		Card treDiFiori = new Card(3,"3", "clubs",true, "src/cards/tre_fiori.png","src/small_cards/tre_fiori.png");
		Card quattroDiFiori = new Card(4,"4", "clubs",true, "src/cards/quattro_fiori.png","src/small_cards/quattro_fiori.png");
		Card cinqueDiFiori = new Card(5,"5", "clubs",true, "src/cards/cinque_fiori.png","src/small_cards/cinque_fiori.png");
		
		Card assoDiFioriB = new Card(1,"A", "clubs",true, "src/cards/asso_fiori.png","src/small_cards/asso_fiori.png");
		Card assoDiCuori = new Card(1,"A", "hearts",true, "src/cards/asso_cuori.png","src/small_cards/asso_cuori.png");
		Card assoDiPicche = new Card(1,"A", "spades",true, "src/cards/asso_picche.png","src/small_cards/asso_picche.png");
		
		Card dieciDiPicche = new Card(10,"10", "spades",true, "src/cards/dieci_picche.png","src/small_cards/dieci_picche.png");
		Card jackDiPicche = new Card(11,"J", "spades",true, "src/cards/jack_picche.png","src/small_cards/jack_picche.png");
		Card donnaDiPicche = new Card(12,"Q", "spades",true, "src/cards/donna_picche.png","src/small_cards/donna_picche.png");
		Card donnaDiCuori = new Card(12,"Q", "hearts",true, "src/cards/donna_cuori.png","src/small_cards/donna_cuori.png");
		Card kappaDiPicche = new Card(13,"K", "spades",true, "src/cards/re_picche.png","src/small_cards/re_picche.png");

		startingCards.addCard(joker);
		startingCards.addCard(assoDiFiori);
		startingCards.addCard(dueDiFiori);
		startingCards.addCard(treDiFiori);
		startingCards.addCard(quattroDiFiori);
		startingCards.addCard(cinqueDiFiori);
		startingCards.addCard(assoDiFioriB);
		startingCards.addCard(assoDiCuori);
		startingCards.addCard(assoDiPicche);
		startingCards.addCard(dieciDiPicche);
		startingCards.addCard(jackDiPicche);
		startingCards.addCard(donnaDiPicche);
		startingCards.addCard(kappaDiPicche);
		
		return startingCards;
	}
	
	
	
}
